package com.foreverwin.jzymes.production.nc.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.foreverwin.jzymes.common.domain.CarrierBind;
import com.foreverwin.jzymes.common.domain.NcData;
import com.foreverwin.jzymes.common.enums.DispositionEnum;
import com.foreverwin.jzymes.common.mapper.NcDataMapper;
import com.foreverwin.jzymes.common.service.*;
import com.foreverwin.jzymes.common.util.CommonMethods;
import com.foreverwin.jzymes.framework.event.AppEvent;
import com.foreverwin.jzymes.framework.event.AppEventPublisher;
import com.foreverwin.jzymes.framework.exception.BusinessException;
import com.foreverwin.jzymes.framework.util.I18nUtil;
import com.foreverwin.jzymes.framework.util.ObjectMapperUtil;
import com.foreverwin.jzymes.production.nc.service.ICarrierNCRecordAdviceService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class CarrierNCRecordAdviceServiceImpl implements ICarrierNCRecordAdviceService {

    @Autowired
    ISiteAdviceService siteAdviceService;
    @Autowired
    IResourceAdviceService resourceAdviceService;
    @Autowired
    INCCodeAdviceService ncCodeAdviceService;
    @Autowired
    ICarrierBindAdviceService carrierBindAdviceService;
    @Autowired
    INCDataAdviceService ncDataAdviceService;
    @Autowired
    ICommonService commonService;
    @Autowired
    NcDataMapper ncDataMapper;
    @Autowired
    AppEventPublisher appEventPublisher;

    /**
     * 不良录入业务处理
     *
     * @param jsonMap
     */
    @Transactional( propagation = Propagation.REQUIRED, rollbackFor = Exception.class )
    public void recordCarrierNC( Map<String,Object> jsonMap, boolean autoPass ){

        /**检查不良录入字段*/
        checkFieldsForRecordNC( jsonMap );

        /**检查不良明细*/
        List<Map<String,Object>> ncList = (List<Map<String, Object>>) jsonMap.get( "ncList" );
        Assert.isTrue( ncList != null && ncList.size() > 0, I18nUtil.getI18nText( "production.nc.ncListNotNull" ) );

        /**添加公用字段*/
        jsonMap.remove( "ncList" );
        for( Map<String,Object> map : ncList ){
            map.putAll( jsonMap );
        }

        /**记录不良数据*/
        List<NcData> ncDataList = ObjectMapperUtil.convertList( ncList, NcData.class );
        recordCarrierNC( (String)jsonMap.get( "site" ), (String) jsonMap.get( "carrier" ), (String) jsonMap.get( "resrce" ), ncDataList, autoPass );
    }

    /**
     * 检查不良录入字段
     *
     * @param headMap
     */
    public void checkFieldsForRecordNC( Map<String,Object> headMap ){

        /**检查站点*/
        siteAdviceService.existSite((String) headMap.get( "site" ));
        /**检查设备*/
        Map<String,Object> resourceMap = resourceAdviceService.existResource( (String) headMap.get( "site" ), (String) headMap.get( "resrce" ));
        /**检查工序*/
        String operation = resourceAdviceService.findOperationByResource( resourceMap );
        headMap.put( "operation", operation );
        /**检查本体*/
        Assert.hasText( ( String )headMap.get( "carrier" ), I18nUtil.getI18nText( "common.carrierNotBlank" ));
    }

    /**
     * 不良数据录入
     *
     * @param ncDataList
     */
    public void recordCarrierNC( String site, String carrier, String resource, List<NcData> ncDataList, boolean autoPass ){
        Date endDateTime = new Date();
        boolean rework = false;
        for( NcData ncData : ncDataList ){

            /**检查物料本体绑定状态*/
            CarrierBind carrierBind = carrierBindAdviceService.findCarrierBindOnBindByItem( ncData.getSite(), ncData.getCarrier(), ncData.getItemBo() );

            /**本体在工序已过站则不允许再记录不良数据*/
            boolean passed = commonService.checkCarrierPassOnOperation( carrierBind, ncData.getOperation() );
            Assert.isTrue( passed == false, I18nUtil.getI18nText( "production.nc.ncForbitByCarrierPassOnOperation", new String[]{ ncData.getCarrier(), ncData.getOperation() } ) );

            /**检查本体物料前面工序是否存在未处置完成的不合格记录（未处置/返工）*/
            NcData ncData1 = ncDataAdviceService.findItemOpenNcDataFromDate( ncData.getSite(), ncData.getCarrier(), ncData.getItemBo() );
            if( ncData1 != null && StringUtils.isNotBlank( ncData.getNcCode() ) ){
                throw BusinessException.build( I18nUtil.getI18nText("production.nc.carrierItemNCExistNotDispose", new String[]{ ncData.getCarrier(), ncData.getItemBo(), ncData1.getOperation(), ncData1.getNcCode() } ) );
            }

            /**检查本体物料在工序是否已记录不合格*/
            NcData ncData2 = ncDataAdviceService.findCarrierNcDataFromDate( ncData.getSite(), ncData.getCarrier(), ncData.getItemBo(), ncData.getOperation() );
            if( ncData2 != null && StringUtils.isNotBlank( ncData.getNcCode() ) ){
                throw BusinessException.build( I18nUtil.getI18nText( "production.nc.carrierItemNCExist", new String[]{ ncData.getCarrier(), ncData.getItemBo(), ncData2.getNcCode() } ) );
            }

            /**填充不良数据字段*/
            ncData.setMachineType( carrierBind.getMachineType() );
            ncData.setNcQty( 1L );
            ncData.setCreatedDateTime( endDateTime );
            ncData.setCreateUserBo( CommonMethods.getUserBo() );

            /**检查不合格代码是否存在*/
            if( StringUtils.isNotBlank( ncData.getNcCode() ) ){
                ncCodeAdviceService.existNCCode( ncData.getSite(), ncData.getNcCode() );
            }else {
                continue;
            }

            /**检查nc是否处置*/
            checkNcDataNotDispose( ncData );

            /**处置方式报废*/
            if( DispositionEnum.SCRAP.getValue().equals( ncData.getDisposition() ) ){
                commonService.saveNcData( ncData, false );

                JSONObject eventData = new JSONObject();
                eventData.put( "SITE", ncData.getSite() );
                eventData.put( "ITEM_BO", ncData.getItemBo() );
                eventData.put( "RESRCE", ncData.getResrce() );
                eventData.put( "QTY", ncData.getNcQty() );
                AppEvent<JSONObject> appEvent = new AppEvent<>( this );
                appEvent.setName( "ITEM_NC_SCRAP_EVENT" );
                appEvent.setData( eventData );
                appEventPublisher.publishEvent( appEvent );

                continue;
            }

            /**处置方式返工*/
            if( DispositionEnum.REWORK.getValue().equals( ncData.getDisposition() ) ){
                rework = true;
                ncData.setIsRework( "true" );
            }

            commonService.saveNcData( ncData, true );
        }

        /**保存不良数据记录、过站信息*/
        if( !rework && autoPass ){
           commonService.sfcPassByCarrier( site, carrier, resource, endDateTime );

            JSONObject eventData = new JSONObject();
            eventData.put( "SITE", site );
            eventData.put( "CARRIER", carrier );
            eventData.put( "RESRCE", resource );
            AppEvent<JSONObject> appEvent = new AppEvent<>( this );
            appEvent.setName( "CARRIER_NC_CHECK_OUT_EVENT" );
            appEvent.setData( eventData );
            appEventPublisher.publishEvent( appEvent );
        }

    }

    /**
     * 检查未处置的不良项目
     *
     * @param ncData
     */
    public void checkNcDataNotDispose( NcData ncData ){
        if( StringUtils.isBlank( ncData.getDisposition() ) ){
            String futureOperation = ncCodeAdviceService.findNCValidOper( ncData.getSite(), ncData.getNcCode() );
            if( StringUtils.isBlank( futureOperation ) ){
                throw BusinessException.build("production.nc.carrierNcNotDispose",new String[]{ ncData.getCarrier(), ncData.getItemBo(),ncData.getNcCode() } );
            }
        }
    }

}
